package com.turbo.cloud.gateway.web.client;

import cn.hutool.core.util.StrUtil;
import com.turbo.cloud.gateway.api.Result;
import com.turbo.cloud.gateway.web.client.model.UmsApiRoleQO;
import com.turbo.cloud.gateway.web.client.model.UmsApiRoleVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.loadbalancer.reactive.ReactorLoadBalancerExchangeFilterFunction;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.client.ClientRequest;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;

import java.util.List;

/**
 * 请求UMS服务接口
 *
 * @author zhangluning
 */
@Slf4j
@Component
public class UmsReactiveWebService {

    private final WebClient webClient;

    final static String QUERY_API_WITH_ROLE_BY_API_URL = "http://turbo-cloud-ums/interface/role/queryApiWithRoleByApiUrl";
    final static String QUERY_API_WITH_ROLE_LIST = "http://turbo-cloud-ums/interface/role/queryApiWithRoleList";

    /**
     * ReactorLoadBalancerExchangeFilterFunction是LoadBalance的一个负载
     * 可以适配nacos的服务发现，将其注入到WebClient即可实现服务名称调用及负载
     */
    public UmsReactiveWebService(ReactorLoadBalancerExchangeFilterFunction lbFunction) {
        this.webClient = WebClient.builder().filter(((request, next) -> {
            ClientRequest filtered = ClientRequest.from(request).build();
            String authorization = request.headers().getFirst(HttpHeaders.AUTHORIZATION);
            if (StrUtil.isNotBlank(authorization)) {
                filtered = ClientRequest.from(request).header(HttpHeaders.AUTHORIZATION, request.headers().getFirst(HttpHeaders.AUTHORIZATION)).build();
            }
            return next.exchange(filtered);
        })).filter(lbFunction).build();
    }

    public Mono<Result<UmsApiRoleVO>> queryApiWithRoleByApiUrl(UmsApiRoleQO umsApiRoleQO) {
        return webClient.post().uri(QUERY_API_WITH_ROLE_BY_API_URL).accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON).bodyValue(umsApiRoleQO).retrieve()
                // 结果转换，将响应转换为什么类型的结果，结果为响应式类型Mono/Flux
                .bodyToMono(new ParameterizedTypeReference<>() {
                });
    }

    public Mono<Result<List<UmsApiRoleVO>>> queryApiWithRoleList() {
        return webClient.post().uri(QUERY_API_WITH_ROLE_LIST).accept(MediaType.APPLICATION_JSON).contentType(MediaType.APPLICATION_JSON).retrieve()
                // 结果转换，将响应转换为什么类型的结果，结果为响应式类型Mono/Flux
                .bodyToMono(new ParameterizedTypeReference<>() {
                });
    }

}
